package com.yidingdui.service.impl;

import com.tencentcloudapi.ai3d.v20250513.Ai3dClient;
import com.tencentcloudapi.ai3d.v20250513.models.*;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.yidingdui.domain.dto.Image3DDto;
import com.yidingdui.domain.vo.ImageVo;
import com.yidingdui.domain.vo.Resultdata;
import com.yidingdui.service.Image3DService;
import com.yidingdui.service.ModelHistoryService;
import com.yidingdui.util.ImageUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;

@Service
@RequiredArgsConstructor
public class Image3DServiceImpl implements Image3DService {

    @Value("${tencenthunyuan.secretId}")
    private String secretId;

    @Value("${tencenthunyuan.secretKey}")
    private String secretKey;
    
    private final ModelHistoryService modelHistoryService;


    @Override
    public Resultdata<ImageVo> getImage3DOfPrompt(Image3DDto image3DDto) {
        try {
            // 1. 实例化认证对象，传入 SecretId 和 SecretKey
            Ai3dClient client = getClient();

            // 5. 实例化一个请求对象，根据你想调用的接口生成
            SubmitHunyuanTo3DJobRequest req = new SubmitHunyuanTo3DJobRequest();

            // 6. 构造请求参数
            // 文生3D示例：设置Prompt参数
            req.setPrompt(image3DDto.getPrompt()); // 中文正向提示词，最多1024字符[1](@ref)
            // 可选参数设置
            req.setEnablePBR(image3DDto.getEnablePBR()); // 是否开启PBR材质生成[1](@ref)
            req.setResultFormat(image3DDto.getResultFormat());
            // 7. 发起请求并处理响应
            Future<Resultdata<ImageVo>> data = getResultdataFuture(client, req);
            return data.get();
        } catch (TencentCloudSDKException e) {
            return Resultdata.error("500", e.getMessage());
        } catch (InterruptedException | ExecutionException e) {
            return Resultdata.error("500", "生成失败，请重新生成");
        }
    }

    @Override
    public Resultdata<ImageVo> getImage3DOfImage(Image3DDto image3DDto,MultipartFile imageFile) {
        try {
            Ai3dClient client = getClient();

            // 5. 实例化一个请求对象，根据你想调用的接口生成
            SubmitHunyuanTo3DJobRequest req = new SubmitHunyuanTo3DJobRequest();

            // 6. 构造请求参数
            // 图生3D示例：你可以设置ImageBase64或ImageUrl（注意：Prompt和图片参数不能同时设置）[1](@ref)
            if (imageFile != null && !imageFile.isEmpty()) {
                String imageBase64 = ImageUtils.convertMultipartFileToBase64(imageFile);
                req.setImageBase64(imageBase64);
            }else {
                return Resultdata.error("500", "必须提供图片文件或图片Base64字符串");
            }

            // 可选参数设置
            req.setEnablePBR(image3DDto.getEnablePBR()); // 是否开启PBR材质生成[1](@ref)
            req.setResultFormat(image3DDto.getResultFormat());
            Future<Resultdata<ImageVo>> data = getResultdataFuture(client, req);
            return data.get();
        } catch (TencentCloudSDKException e) {
            return Resultdata.error("500", e.getMessage());
        } catch (Exception e) {
            return Resultdata.error("500", "图片转换失败: " + e.getMessage());
        }
    }

    private Ai3dClient getClient() {
        // 1. 实例化认证对象，传入 SecretId 和 SecretKey
        Credential cred = new Credential(
                secretId,
                secretKey);

        // 2. 实例化一个HTTP配置选项，可选的，可以设置代理、超时等
        HttpProfile httpProfile = new HttpProfile();
        httpProfile.setEndpoint("ai3d.tencentcloudapi.com"); // 指定接入点域名[1](@ref)

        // 3. 实例化一个客户端配置对象，可以指定签名方式、超时时间等
        ClientProfile clientProfile = new ClientProfile();
        clientProfile.setHttpProfile(httpProfile);

        // 4. 实例化要请求产品（AI3D）的客户端对象
        // 请注意：Ai3dClient 和命名空间可能需要根据实际SDK调整，例如可能是 HunyuanClient 或其他，请以官方文档为准
        Ai3dClient client = new Ai3dClient(cred, "ap-guangzhou", clientProfile); // 地域列表需参考文档[1](@ref)
        return client;
    }

    private static Future<Resultdata<ImageVo>> getResultdataFuture(Ai3dClient client, SubmitHunyuanTo3DJobRequest req) throws TencentCloudSDKException {
        // 7. 发起请求并处理响应
        SubmitHunyuanTo3DJobResponse resp = client.SubmitHunyuanTo3DJob(req);

        // 响应对象中包含JobId，用于后续查询任务状态和获取生成的3D模型数据[1](@ref)
        System.out.println("JobId: " + resp.getJobId());
        System.out.println("RequestId: " + resp.getRequestId()); // 用于排查问题

        QueryHunyuanTo3DJobRequest queryHunyuanTo3DJob = new QueryHunyuanTo3DJobRequest();
        queryHunyuanTo3DJob.setJobId(resp.getJobId());
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), new ThreadPoolExecutor.CallerRunsPolicy());
        Future<Resultdata<ImageVo>> data = threadPoolExecutor.submit(() -> {
            while (true) {
                try {
                    QueryHunyuanTo3DJobResponse queryHunyuanTo3DJobResponse = client.QueryHunyuanTo3DJob(queryHunyuanTo3DJob);
                    String status = queryHunyuanTo3DJobResponse.getStatus();
                    if (status.equals("DONE")) {
                        File3D[] resultFile3Ds = queryHunyuanTo3DJobResponse.getResultFile3Ds();
                        File3D resultFile3D = resultFile3Ds[0];
                        String url = resultFile3D.getUrl();
                        String type = resultFile3D.getType();
                        return Resultdata.success(ImageVo.of(url, type));
                    } else if (status.equals("FAIL")) {
                        String errorMessage = queryHunyuanTo3DJobResponse.getErrorMessage();
                        return Resultdata.error("500", errorMessage);
                    } else {
                        TimeUnit.MINUTES.sleep(1);
                    }
                } catch (TencentCloudSDKException e) {
                    return Resultdata.error("500", e.getMessage());
                } catch (InterruptedException e) {
                    return Resultdata.error("500", "生成失败，请重新生成");
                }
            }
        });
        return data;
    }
    
    @Override
    @Async
    public void generateAsync(String taskId, String prompt, Boolean enablePBR, String resultFormat) {
        try {
            Ai3dClient client = getClient();
            
            SubmitHunyuanTo3DJobRequest req = new SubmitHunyuanTo3DJobRequest();
            req.setPrompt(prompt);
            req.setEnablePBR(enablePBR);
            req.setResultFormat(resultFormat);
            
            SubmitHunyuanTo3DJobResponse resp = client.SubmitHunyuanTo3DJob(req);
            String jobId = resp.getJobId();
            
            // 轮询任务状态
            QueryHunyuanTo3DJobRequest queryReq = new QueryHunyuanTo3DJobRequest();
            queryReq.setJobId(jobId);
            
            while (true) {
                QueryHunyuanTo3DJobResponse queryResp = client.QueryHunyuanTo3DJob(queryReq);
                String status = queryResp.getStatus();
                
                if ("DONE".equals(status)) {
                    File3D[] resultFile3Ds = queryResp.getResultFile3Ds();
                    if (resultFile3Ds != null && resultFile3Ds.length > 0) {
                        String url = resultFile3Ds[0].getUrl();
                        modelHistoryService.updateTaskSuccess(taskId, url);
                    } else {
                        modelHistoryService.updateTaskFailure(taskId, "生成结果为空");
                    }
                    break;
                } else if ("FAIL".equals(status)) {
                    String errorMessage = queryResp.getErrorMessage();
                    modelHistoryService.updateTaskFailure(taskId, errorMessage);
                    break;
                } else {
                    // 继续等待
                    TimeUnit.MINUTES.sleep(1);
                }
            }
        } catch (Exception e) {
            modelHistoryService.updateTaskFailure(taskId, "生成失败: " + e.getMessage());
        }
    }
    
    @Override
    @Async
    public void generateFromImageAsync(String taskId, Boolean enablePBR, String resultFormat, MultipartFile imageFile) {
        try {
            Ai3dClient client = getClient();
            
            SubmitHunyuanTo3DJobRequest req = new SubmitHunyuanTo3DJobRequest();
            if (imageFile != null && !imageFile.isEmpty()) {
                String imageBase64 = ImageUtils.convertMultipartFileToBase64(imageFile);
                req.setImageBase64(imageBase64);
            } else {
                modelHistoryService.updateTaskFailure(taskId, "必须提供图片文件");
                return;
            }
            
            req.setEnablePBR(enablePBR);
            req.setResultFormat(resultFormat);
            
            SubmitHunyuanTo3DJobResponse resp = client.SubmitHunyuanTo3DJob(req);
            String jobId = resp.getJobId();
            
            // 轮询任务状态
            QueryHunyuanTo3DJobRequest queryReq = new QueryHunyuanTo3DJobRequest();
            queryReq.setJobId(jobId);
            
            while (true) {
                QueryHunyuanTo3DJobResponse queryResp = client.QueryHunyuanTo3DJob(queryReq);
                String status = queryResp.getStatus();
                
                if ("DONE".equals(status)) {
                    File3D[] resultFile3Ds = queryResp.getResultFile3Ds();
                    if (resultFile3Ds != null && resultFile3Ds.length > 0) {
                        String url = resultFile3Ds[0].getUrl();
                        modelHistoryService.updateTaskSuccess(taskId, url);
                    } else {
                        modelHistoryService.updateTaskFailure(taskId, "生成结果为空");
                    }
                    break;
                } else if ("FAIL".equals(status)) {
                    String errorMessage = queryResp.getErrorMessage();
                    modelHistoryService.updateTaskFailure(taskId, errorMessage);
                    break;
                } else {
                    // 继续等待
                    TimeUnit.MINUTES.sleep(1);
                }
            }
        } catch (Exception e) {
            modelHistoryService.updateTaskFailure(taskId, "生成失败: " + e.getMessage());
        }
    }
}